﻿unit TestFormU;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, AVTypes, Rtti, AVData,
  Vcl.Grids, AVUtils, Vcl.ComCtrls, AVGrid, AVCustomGrid, Vcl.ExtCtrls,
  Vcl.Themes;

type
  TestRecord = record
    id: integer;
    name: string;
  end;

type
  TTestRec = record
    id: integer;
    name: string;
  end;

  TForm3 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button7: TButton;
    Button6: TButton;
    Label1: TLabel;
    eRowCount: TEdit;
    Label2: TLabel;
    rbByName: TRadioButton;
    rbByIndex: TRadioButton;
    rbDirect: TRadioButton;
    chbWithVar: TCheckBox;
    lTiks: TLabel;
    Label3: TLabel;
    DrawGrid: TDrawGrid;
    AVGrid: TAVGrid;
    Panel1: TPanel;
    Label4: TLabel;
    e_RowCount: TEdit;
    Button8: TButton;
    chbReadOnly: TCheckBox;
    Splitter1: TSplitter;
    memo: TMemo;
    Splitter2: TSplitter;
    Label5: TLabel;
    e_filter: TEdit;
    Label6: TLabel;
    e_filter_col: TEdit;
    CheckBox1: TCheckBox;
    cbTheme: TComboBox;
    chbTheme: TCheckBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure DrawGridDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure Button7Click(Sender: TObject);
    procedure chbReadOnlyClick(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure AVGridBeforeSort(Sender: TAVGrid;
      SortColumns: TArray<AVData.TAVBaseColumn>);
    procedure AVGridAfterSort(Sender: TAVGrid;
      SortColumns: TArray<AVData.TAVBaseColumn>);
    procedure e_filterChange(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure cbThemeChange(Sender: TObject);
    procedure chbThemeClick(Sender: TObject);
  private
    TestRec: TestRecord;
    Grid: TAVData;

    cint: TAVColumn<integer>;
    cstring: TAVColumn<string>;
    cbyte: TAVColumn<byte>;
    cint16: TAVColumn<int16>;
    cint32: TAVColumn<int32>;
    cNative: TAVColumn<NativeInt>;
    cInt64: TAVColumn<Int64>;
    cdouble: TAVColumn<double>;
    cobj: TAVColumn<TObject>;
    cdate: TAVColumn<TDateTime>;
    cbool: TAVColumn<boolean>;
    cvalue: TAVColumn<TValue>;
    cvar: TAVColumn<Variant>;
    cbitarr: TAVColumn<TBitArray>;
    cword: TAVColumn<Word>;
    crec: TAVColumn<TTestRec>;

    fSortStart: Cardinal;

    procedure ClearGrid;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

constructor TForm3.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Grid := TAVData.Create;

  cint := Grid.AddCol<integer>('int');
  cstring := Grid.AddCol<string>('string');
  cbyte := Grid.AddCol<byte>('byte');
  cint16 := Grid.AddCol<int16>('int16');
  cint32 := Grid.AddCol<int32>('int32');
  cNative := Grid.AddCol<NativeInt>('Native');
  cInt64 := Grid.AddCol<Int64>('Int64');
  cdouble := Grid.AddCol<double>('double');
  cobj := Grid.AddCol<TObject>('obj');
  cdate := Grid.AddCol<TDateTime>('date');
  cbool := Grid.AddCol<boolean>('bool');
  cvalue := Grid.AddCol<TValue>('value');
  cvar := Grid.AddCol<Variant>('var');
  cbitarr := Grid.AddCol<TBitArray>('bitarr');
  cword := Grid.AddCol<Word>('word');
  crec := Grid.AddCol<TTestRec>('rec');
end;

destructor TForm3.Destroy;
begin
  Grid.Free;
  inherited Destroy;
end;

procedure TForm3.DrawGridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  if ACol = 0 then begin
    if (ARow > 0) and (ARow <= Grid.DisplayRowCount) then
      DrawGrid.Canvas.TextRect(Rect, Rect.Left + 1, Rect.Top + 1, IntToStr(ARow - 1));
  end else
  if ARow = 0 then begin
    if (ACol > 0) and (ACol <= Grid.ColumnCount) then
      DrawGrid.Canvas.TextRect(Rect, Rect.Left + 1, Rect.Top + 1, Grid.Columns[ACol - 1].Name);
  end else begin
    DrawGrid.Canvas.TextRect(Rect, Rect.Left + 1, Rect.Top + 1, Grid.DisplayValue[ACol - 1, ARow - 1].AsString);
  end;
end;

procedure TForm3.e_filterChange(Sender: TObject);
begin
  AVGrid.Data.SetFilter(e_filter_col.Text, e_filter.Text);
  AVGrid.UpdateRowCount;
end;

procedure TForm3.FormCreate(Sender: TObject);
var i: integer;
    styles: TArray<string>;
begin
  styles := TStyleManager.StyleNames;
  for i := Low(styles) to High(styles) do
    cbTheme.Items.Add(styles[i]);
  if Assigned(TStyleManager.ActiveStyle) then
    cbTheme.ItemIndex := cbTheme.Items.IndexOf(TStyleManager.ActiveStyle.Name);
end;

procedure TForm3.AVGridAfterSort(Sender: TAVGrid;
  SortColumns: TArray<AVData.TAVBaseColumn>);
begin
  memo.Lines.Add('sort:' + SortColumns[0].Name + ' = ' + IntToStr(GetTickCount - fSortStart));
end;

procedure TForm3.AVGridBeforeSort(Sender: TAVGrid;
  SortColumns: TArray<AVData.TAVBaseColumn>);
begin
  fSortStart := GetTickCount;
end;

procedure TForm3.Button1Click(Sender: TObject);
var
  b: byte;
  bitArr: TBitArray;
begin
  b := 4;
  bitArr.Byte[0] := b;
  if bitArr[2] then ShowMessage('OK');
  bitArr[2] := false;
  bitArr[3] := true;
  b := bitArr.byte[0];

  bitArr.ByteBit[1,4] := true;
  b := bitArr.byte[1];
  ShowMessage(IntToStr(b));
end;



procedure TForm3.Button2Click(Sender: TObject);
var v: TValue;
    r: TestRecord;
begin
  r.id := 5;
  r.name := 'test name';
  v := TValue.From<TestRecord>(r);
  TestRec := v.AsType<TestRecord>;
end;

procedure TForm3.Button3Click(Sender: TObject);
begin
  ShowMessage(IntToStr(TestRec.id) + ' - ' + TestRec.name);
end;

procedure TForm3.Button4Click(Sender: TObject);
var t: TRttiType;
    f: TRttiField;
    s: string;
    v: TValue;
    av: TAVValue;
begin
  t := RttiContext.GetType(TypeInfo(TestRecord));
  s := '';
  for f in t.GetFields do begin
    v :=  f.GetValue(@TestRec);
    av.PointTo<TValue>(v);
    s := s + f.Name + ' = ' + av.AsString + #13#10;
  end;
  ShowMessage(s);
end;

procedure TForm3.Button5Click(Sender: TObject);
var av: TAVValue;
    s: string;
begin
  av.PointTo<TestRecord>(TestRec);
  s := IntToStr(av.AsRtti['id'].AsInteger) + ' - ' + av.AsRtti['name'].AsString;
  ShowMessage(s);
end;

procedure TForm3.Button6Click(Sender: TObject);
var i: integer;
    n64: Int64;
    bitArr: TBitArray;
    rec: TTestRec;
    startTiks: DWORD;
    withVar: boolean;
begin
  ClearGrid;

  startTiks := GetTickCount;
  Grid.DisplayRowCount := AVUtils.StrToIntAnyway(eRowCount.Text);
  withVar := chbWithVar.Checked;

  if rbByName.Checked then begin
    for i := 0 to Grid.DisplayRowCount - 1 do begin
      Grid['int', i].AsInteger := i;
      Grid['string', i].AsString := 'row ' + IntToStr(i);
      Grid['byte', i].AsInteger := i;
      Grid['int16', i].AsInteger := i;
      Grid['int32', i].AsInteger := i;
      Grid['Native', i].AsInteger := i;
      n64 := MaxInt;
      n64 := n64 * i;
      Grid['Int64', i].AsInt64 := n64;
      Grid['double', i].AsFloat := (i+10)/(i + 1);
      if i mod 3 = 0
        then Grid['obj', i].AsObject := Self
        else Grid['obj', i].AsObject := nil;
      Grid['date', i].AsDate := Date - i;
      Grid['bool', i].AsBool := i mod 3 = 0;
      if withVar then begin
        case i mod 3 of
          0: Grid['value', i].AsValue := TValue.From<integer>(i);
          1: Grid['value', i].AsValue := TValue.From<string>('str ' + IntToStr(i));
          2: Grid['value', i].AsValue := TValue.From<real>((i+5)/(i+2));
        end;
        case i mod 3 of
          0: Grid['var', i].AsVariant := i;
          1: Grid['var', i].AsVariant := 'str ' + IntToStr(i);
          2: Grid['var', i].AsVariant := (i+5)/(i+2);
        end;
      end;
      bitArr := Grid['bitarr', i].AsBitArray;
      bitArr.SetData(i, SizeOf(i));
      Grid['bitarr', i].AsBitArray := bitArr;
      Grid['word', i].AsInteger := i;

      rec.id := i + 1;
      rec.name := 'rec ' + IntToStr(i + 1);
      Grid['rec', i].SetAsType<TTestRec>(rec);
    end;
  end else
  if rbByIndex.Checked then begin
    for i := 0 to Grid.DisplayRowCount - 1 do begin
      Grid.DisplayValue[0, i].AsInteger := i;
      Grid.DisplayValue[1, i].AsString := 'row ' + IntToStr(i);
      Grid.DisplayValue[2, i].AsInteger := i;
      Grid.DisplayValue[3, i].AsInteger := i;
      Grid.DisplayValue[4, i].AsInteger := i;
      Grid.DisplayValue[5, i].AsInteger := i;
      n64 := MaxInt;
      n64 := n64 * i;
      Grid.DisplayValue[6, i].AsInt64 := n64;
      Grid.DisplayValue[7, i].AsFloat := (i+10)/(i + 1);
      if i mod 3 = 0
        then Grid.DisplayValue[8, i].AsObject := Self
        else Grid.DisplayValue[8, i].AsObject := nil;
      Grid.DisplayValue[9, i].AsDate := Date - i;
      Grid.DisplayValue[10, i].AsBool := i mod 3 = 0;
      if withVar then begin
        case i mod 3 of
          0: Grid.DisplayValue[11, i].AsValue := TValue.From<integer>(i);
          1: Grid.DisplayValue[11, i].AsValue := TValue.From<string>('str ' + IntToStr(i));
          2: Grid.DisplayValue[11, i].AsValue := TValue.From<real>((i+5)/(i+2));
        end;
        case i mod 3 of
          0: Grid.DisplayValue[12, i].AsVariant := i;
          1: Grid.DisplayValue[12, i].AsVariant := 'str ' + IntToStr(i);
          2: Grid.DisplayValue[12, i].AsVariant := (i+5)/(i+2);
        end;
      end;
      bitArr := Grid.DisplayValue[13, i].AsBitArray;
      bitArr.SetData(i, SizeOf(i));
      Grid.DisplayValue[13, i].AsBitArray := bitArr;
      Grid.DisplayValue[14, i].AsInteger := i;

      rec.id := i + 1;
      rec.name := 'rec ' + IntToStr(i + 1);
      Grid.DisplayValue[15, i].SetAsType<TTestRec>(rec);
    end;
  end else begin
    for i := 0 to Grid.DisplayRowCount - 1 do begin
      cint[i] := i;
      cstring[i] := 'row ' + IntToStr(i);
      cbyte[i] := i;
      cint16[i] := i;
      cint32[i] := i;
      cNative[i] := i;
      n64 := MaxInt;
      n64 := n64 * i;
      cInt64[i] := n64;
      cdouble[i] := (i+10)/(i + 1);
      if i mod 3 = 0
        then cobj[i] := Self
        else cobj[i] := nil;
      cdate[i] := Date - i;
      cbool[i] := i mod 3 = 0;
      if withVar then begin
        case i mod 3 of
          0: cvalue[i] := TValue.From<integer>(i);
          1: cvalue[i] := TValue.From<string>('str ' + IntToStr(i));
          2: cvalue[i] := TValue.From<real>((i+5)/(i+2));
        end;
        case i mod 3 of
          0: cvar[i] := i;
          1: cvar[i] := 'str ' + IntToStr(i);
          2: cvar[i] := (i+5)/(i+2);
        end;
      end;
      bitArr := cbitarr[i];
      bitArr.SetData(i, SizeOf(i));
      cbitarr[i] := bitArr;
      cword[i] := i;

      rec.id := i + 1;
      rec.name := 'rec ' + IntToStr(i + 1);
      crec[i] := rec;
    end;
  end;

  DrawGrid.RowCount := Grid.DisplayRowCount + 1;
  DrawGrid.ColCount := Grid.ColumnCount + 1;
  DrawGrid.Invalidate;

  lTiks.Caption := IntToStr(GetTickCount - startTiks);
end;

procedure TForm3.CheckBox1Click(Sender: TObject);
begin
  AVGrid.AlwaysShowGroupPannel := CheckBox1.Checked;
end;

procedure TForm3.ClearGrid;
begin
  Grid.DisplayRowCount := 0;

  DrawGrid.RowCount := 2;
  DrawGrid.Invalidate;
  Application.ProcessMessages;
end;

procedure TForm3.Button7Click(Sender: TObject);
begin
  ClearGrid;
end;

procedure TForm3.Button8Click(Sender: TObject);
var i: integer;
    RCount: integer;
    oldTick: Cardinal;
begin
  RCount := StrToInt(e_RowCount.Text);
  oldTick := GetTickCount;
  AVGrid.Data.DisplayRowCount := RCount;
  memo.Lines.Add('Set RowCount = ' + IntToStr(GetTickCount - oldTick));
  oldTick := GetTickCount;
  for i := 0 to RCount - 1 do begin
    AVGrid.Data['str1', i].AsString := 'str1 ' + IntToStr(i);
    AVGrid.Data['str2', i].AsString := 'str2 ' + IntToStr(RCount - i);
    AVGrid.Data['int', i].AsInteger := i;
    AVGrid.Data['float', i].AsFloat := i + i/3;
    AVGrid.Data['date', i].AsDate := Date - Trunc(RCount/2) + i + i / 1440;
    AVGrid.Data['bool', i].AsBool := i mod 3 = 0;
    AVGrid.Data['int64', i].AsInt64 := Int64(MaxInt) * 5 + i;
  end;
  AVGrid.UpdateRowCount;
  memo.Lines.Add('Fill Grid = ' + IntToStr(GetTickCount - oldTick));
end;

procedure TForm3.cbThemeChange(Sender: TObject);
begin
  if cbTheme.ItemIndex >= 0 then
    TStyleManager.TrySetStyle(cbTheme.Text);
end;

procedure TForm3.chbReadOnlyClick(Sender: TObject);
begin
  AVGrid.ReadOnly := chbReadOnly.Checked;
end;

procedure TForm3.chbThemeClick(Sender: TObject);
begin
  if chbTheme.Checked then
    TStyleManager.TrySetStyle(cbTheme.Text)
  else
    TStyleManager.TrySetStyle('');
end;

end.
